package com.siyoumi.app.modules.lucky_num.service;

import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.lucky_num.entity.LuckyNumType;
import com.siyoumi.app.modules.lucky_num.service.Impl.LNumGroupImplDef;
import com.siyoumi.app.modules.lucky_num.vo.LNumGetVo;
import com.siyoumi.app.modules.lucky_num.vo.VaLnumGroup;
import com.siyoumi.app.service.LnumGroupService;
import com.siyoumi.app.service.LnumNumService;
import com.siyoumi.app.service.LnumWinService;
import com.siyoumi.app.service.SysStockService;
import com.siyoumi.component.XApp;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.service.IWebService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

//号码组
@Slf4j
public abstract class SvcLNumGroup
        implements IWebService {
    static public SvcLNumGroup getBean() {
        return new LNumGroupImplDef();
    }

    static public LnumGroupService getApp() {
        return LnumGroupService.getBean();
    }

    static public boolean isLuckyNum(String type) {
        if (LuckyNumType.LUCKY_NUM.getKey().equals(type)) {
            return true;
        }

        return false;
    }

    public LnumGroup getEntityByKey(String groupKey) {
        JoinWrapperPlus<LnumGroup> query = listQuery();
        query.eq("lngroup_key", groupKey);
        return getApp().first(query);
    }

    public LnumNum getEntityNum(String groupId, long num) {
        JoinWrapperPlus<LnumNum> query = numQuery(groupId, num);
        query.eq("lnum_num", num);
        return LnumNumService.getBean().first(query);
    }

    public LnumNum getEntityNumByKey(String groupId, String key) {
        JoinWrapperPlus<LnumNum> query = numQuery(groupId, InputData.getIns());
        query.eq("lnum_key", key);
        return LnumNumService.getBean().first(query);
    }

    public JoinWrapperPlus<LnumNum> numQuery(String groupId, long num) {
        InputData inputData = InputData.getIns();
        inputData.put("num", num + "");
        return numQuery(groupId, inputData);
    }

    public Long numCount(String groupId, String setId) {
        InputData inputData = InputData.getIns();
        inputData.put("set_id", setId);
        JoinWrapperPlus<LnumNum> query = numQuery(groupId, inputData);
        return LnumNumService.getBean().count(query);
    }

    public Long numCount(String openid) {
        InputData inputData = InputData.getIns();
        inputData.put("openid", openid);
        JoinWrapperPlus<LnumNum> query = numQuery(null, inputData);
        return LnumNumService.getBean().count(query);
    }

    public JoinWrapperPlus<LnumNum> numQuery(String groupId, InputData inputData) {
        String openid = inputData.input("openid");
        String createBegin = inputData.input("create_begin");
        String createEnd = inputData.input("create_end");
        String num = inputData.input("num");
        String setId = inputData.input("set_id");

        JoinWrapperPlus<LnumNum> query = LnumNumService.getBean().join();
        query.eq("lnum_x_id", XHttpContext.getX())
                //.eq("lnum_group_id", groupId)
                .eq("lnum_invaild", 0);
        if (XStr.hasAnyText(groupId)) { //组
            query.eq("lnum_group_id", groupId);
        }
        if (XStr.hasAnyText(setId)) { //号码配置ID
            query.eq("lnum_set_id", setId);
        }
        if (XStr.hasAnyText(openid)) { //用户ID
            query.eq("lnum_wxuser_id", openid);
        }
        if (XStr.hasAnyText(createBegin) && XStr.hasAnyText(createEnd)) { //创建时间
            LocalDateTime b = XDate.parse(createBegin);
            LocalDateTime e = XDate.parse(createEnd);
            query.between("lnum_create_date", b, e);
        }
        if (XStr.hasAnyText(num)) { //号码
            String[] numArr = num.split(",");
            query.in("lnum_num", Arrays.asList(numArr));
        }

        return query;
    }

    public JoinWrapperPlus<LnumWin> numWinQuery(String groupId, InputData inputData) {
        String openid = inputData.input("openid");
        String createBegin = inputData.input("create_begin");
        String createEnd = inputData.input("create_end");
        String num = inputData.input("num");
        String sessionId = inputData.input("session_id");

        JoinWrapperPlus<LnumWin> query = LnumWinService.getBean().join();
        query.eq("lnwin_x_id", XHttpContext.getX());

        if (XStr.hasAnyText(groupId)) { //号码组
            query.eq("lnwin_group_id", groupId);
        }
        if (XStr.hasAnyText(sessionId)) { //奖品期
            query.eq("lnwin_session_id", sessionId);
        }
        if (XStr.hasAnyText(openid)) { //用户ID
            query.eq("lnwin_wxuser_id", openid);
        }
        if (XStr.hasAnyText(createBegin) && XStr.hasAnyText(createEnd)) { //创建时间
            LocalDateTime b = XDate.parse(createBegin);
            LocalDateTime e = XDate.parse(createEnd);
            query.between("lnwin_create_date", b, e);
        }
        if (XStr.hasAnyText(num)) { //号码
            String[] numArr = num.split(",");
            query.in("lnwin_num", Arrays.asList(numArr));
        }

        return query;
    }


    public JoinWrapperPlus<LnumGroup> listQuery() {
        return listQuery(InputData.getIns());
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<LnumGroup> listQuery(InputData inputData) {
        String name = inputData.input("name");
        String type = inputData.input("type");

        JoinWrapperPlus<LnumGroup> query = getApp().join();
        query.eq("lngroup_x_id", XHttpContext.getX())
                .eq("lngroup_del", 0);
        getApp().addQueryAcc(query);
        //排序
        query.orderByAsc("lngroup_order")
                .orderByDesc("lngroup_id");
        if (XStr.hasAnyText(name)) { //名称
            query.like("lngroup_name", name);
        }
        if (XStr.hasAnyText(type)) { //类型
            query.eq("lngroup_type", type);
        }

        return query;
    }

    public XReturn edit(InputData inputData, VaLnumGroup vo) {
        List<String> ignoreField = new ArrayList<>();
        if (inputData.isAdminEdit()) {
            ignoreField.add("lngroup_acc_id");
        }

        vo.setLnset_acc_id(vo.getLngroup_acc_id());

        return XApp.getTransaction().execute(status -> {
            XReturn r = getApp().saveEntity(inputData, vo, true, ignoreField);
            LnumGroup entity = r.getData("entity");

            if (isLuckyNum(entity.getLngroup_type())) {
                //集卡类型
                vo.setLnset_name(entity.getLngroup_name());
                vo.setLnset_group_id(entity.getLngroup_id());
                SvcLnumNumSet.getBean().editSave(entity.getLngroup_id(), vo);
            }


            return r;
        });
    }

    /**
     * 删除
     */
    @SneakyThrows
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn delete(List<String> ids) {
        XReturn r = XReturn.getR(0);

        List<LnumGroup> listGroup = getApp().get(ids, XHttpContext.getX());
        //集卡类型处理
        List<String> groupIds = listGroup.stream().filter(item -> isLuckyNum(item.getLngroup_type())).map(item -> item.getLngroup_id()).collect(Collectors.toList());
        if (groupIds.size() > 0) {
            //删除组，同时删除号码配置
            SvcLnumNumSet.getBean().delete(groupIds);
        }


        getApp().delete(ids);


        return r;
    }


    public XReturn numGetCan(LNumGetVo vo) {
        LnumNumSet entitySet = SvcLnumNumSet.getApp().first(vo.getSet_id());
        if (entitySet == null) {
            return XReturn.getR(20161, "set_id异常");
        }
        LnumGroup entityGroup = SvcLNumGroup.getApp().first(entitySet.getLnset_group_id());
        if (entityGroup == null) {
            return XReturn.getR(20159, "号码组参数异常");
        }

        LnumNum entityNum = getEntityNumByKey(entityGroup.getKey(), vo.getKey());
        if (entityNum != null) {
            return XReturn.getR(20169, "已领取过");
        }

        XReturn r = SvcLnumNumSet.getBean().valid(entitySet, getOpenid());
        if (r.err()) {
            return r;
        }

        return EnumSys.OK.getR();
    }

    /**
     * 计算也中奖号码
     *
     * @param vo
     */
    abstract public Long numGen(LNumGetVo vo);

    public XReturn numGet(LNumGetVo vo) {
        XReturn r = numGetCan(vo);
        if (r.err()) {
            return r;
        }

        LnumNumSet entitySet = SvcLnumNumSet.getApp().first(vo.getSet_id());

        //生成号码
        Long num = numGen(vo);

        return XApp.getTransaction().execute(status -> {
            LnumNum entityNum = new LnumNum();
            entityNum.setLnum_x_id(XHttpContext.getX());
            entityNum.setLnum_key(vo.getKey());
            entityNum.setLnum_group_id(entitySet.getLnset_group_id());
            entityNum.setLnum_wxuser_id(getOpenid());
            entityNum.setLnum_set_id(vo.getSet_id());
            entityNum.setLnum_key(num.toString());
            entityNum.setLnum_num(num);
            entityNum.setAutoID();
            LnumNumService.getBean().save(entityNum);

            //扣库存
            SysStockService.getBean().subStock(vo.getSet_id(), 1L);

            //更新自己领取号码数
            SvcLNumUser.getBean().updateGetCardCount(entityNum.getLnum_wxuser_id(), false);

            XReturn rr = XReturn.getR(0);
            rr.setData("entity_num", entityNum);

            return rr;
        });

    }
}
